﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using SimpleJson;
using UnityEditor;
using UnityEditor.Experimental.UIElements;
using UnityEngine;
using UnityEngine.UI;

public class JsonEditor : EditorWindow
{
    private Vector2 scroPos;
    private string fpath = "Assets/Resources/Json/";
    private TableClass _table;
    private TableSetClass _tableSet;
    private GUIStyle _style;
    private GUIStyle tipsStyle;
    private string tips;
    private Color tipsColor;

    private int needWidth;
    private int needHeight;


    [MenuItem("工具/Json编辑")]
    static void Init()
    {
        JsonEditor jsonEditor = GetWindow<JsonEditor>();
        jsonEditor.titleContent = new GUIContent("Json编辑", Resources.Load<Texture>("Icon/eg"));
    }

    private void OnGUI()
    {
        tipsStyle = new GUIStyle();
        tipsStyle.normal.textColor = tipsColor;

        _style = new GUIStyle("box");
        _style.normal.textColor = Color.magenta;
        scroPos = GUI.BeginScrollView(new Rect(0, 0, position.width, position.height),
            scroPos, new Rect(0, 0, needWidth, needHeight));

        GUI.Label(new Rect(10, 10, 40, 20), "路径:");
        fpath = GUI.TextField(new Rect(50, 10, 700, 20), fpath);
        if (GUI.Button(new Rect(10, 35, 40, 20), "新建"))
        {
            NewBtn();
        }

        if (GUI.Button(new Rect(55, 35, 40, 20), "保存"))
        {
            SaveBtn();
        }

        if (GUI.Button(new Rect(100, 35, 40, 20), "打开"))
        {
            OpenBtn();
        }

        GUI.Label(new Rect(145, 35, 400, 20), tips, tipsStyle);

        GUI.Label(new Rect(10, 60, 700, 20), "===========================================================");
        ShowType();
        ShowTag();
        ShowTable();
        GUI.EndScrollView();
    }

    private void ShowType()
    {
        if (_table != null && _table.typeList != null && _table.keyList.Count > 0)
        {
            for (int i = 0; i < _table.typeList.Count; i++)
            {
                TypeEnum oldtype = _table.typeList[i];
                _table.typeList[i] =
                    (TypeEnum) EditorGUI.EnumPopup(new Rect(10 + i * 75, 80, 73, 20), _table.typeList[i]);
//                if (oldtype != _table.typeList[i] && _table.typeList[i] == TypeEnum.List)
//                {
//                    for (int j = 0; j < _tableSet.valueList.Count; j++)
//                    {
//                        if (!(_tableSet.valueList[j].valueList[i] is Table))
//                        {
//                            _tableSet.valueList[j].valueList[i] = new Table();
//                        }
//                    }
//                }
            }
        }
    }

    private void ShowTag()
    {
        if (_table != null && _table.keyList != null)
        {
            if (_table.keyList.Count > 0)
            {
                for (int i = 0; i < _table.keyList.Count; i++)
                {
                    _table.keyList[i] = GUI.TextField(new Rect(10 + i * 75, 100, 73, 20),
                        _table.keyList[i], _style);
                    if (GUI.Button(new Rect(10 + i * 75, 125, 73, 20), "删除"))
                    {
                        _table.keyList.RemoveAt(i);
                        _table.typeList.RemoveAt(i);
                        for (int j = 0; j < _tableSet.valueList.Count; j++)
                        {
                            _tableSet.valueList[j].valueList.RemoveAt(i);
                        }
                    }
                }
            }


            if (GUI.Button(new Rect(10 + _table.keyList.Count * 75, 100, 60, 20), "添加"))
            {
                _table.keyList.Add("new tag");
                _table.typeList.Add(TypeEnum.String);
                for (int i = 0; i < _tableSet.valueList.Count; i++)
                {
                    _tableSet.valueList[i].valueList.Add("value" + _tableSet.valueList[i].valueList.Count);
                }
            }

            needWidth = 160 + _table.keyList.Count * 75;
        }
        else
        {
            needWidth = 0;
            needHeight = 0;
        }
    }

    private void ShowTable()
    {
        if (_table != null && _table.keyList != null)
        {
            for (int i = 0; i < _tableSet.valueList.Count; i++)
            {
                for (int j = 0; j < _tableSet.valueList[i].valueList.Count; j++)
                {
//                    if (_table.typeList[j] != TypeEnum.List)
                    {
                        _tableSet.valueList[i].valueList[j] = GUI.TextField(new Rect(10 + j * 75, 155 + i * 25, 73, 20),
                            _tableSet.valueList[i].valueList[j].ToString());
                    }
//                    else
//                    {
//                        if (GUI.Button(new Rect(10 + j * 75, 155 + i * 25, 73, 20), "编辑"))
//                        {
//                            Debug.Log("列表" + i + "," + j);
//                            JsonSubEditor jse = GetWindow<JsonSubEditor>();
//                            Table tb = (Table) _tableSet.valueList[i].valueList[j];
//                            jse._table = tb.talbe;
//                            jse._tableSet = tb.tableSet;
//                            jse.Show();
//                        }
//                    }
                }

                if (GUI.Button(new Rect(10 + _table.keyList.Count * 75, 155 + i * 25, 60, 20), "添加"))
                {
                    TableDataClass tableDataClass = new TableDataClass(_table.typeList);
                    _tableSet.valueList.Insert(i + 1, tableDataClass);
                }

                if (GUI.Button(new Rect(85 + _table.keyList.Count * 75, 155 + i * 25, 60, 20), "删除"))
                {
                    _tableSet.valueList.RemoveAt(i);
                }
            }

            needHeight = 160 + _tableSet.valueList.Count * 25;
        }
        else
        {
            needHeight = 0;
            needWidth = 0;
        }
    }

    private void NewBtn()
    {
        _table = new TableClass();
        _tableSet = new TableSetClass();
    }

    private void SaveBtn()
    {
        SaveJson();
    }

    private void OpenBtn()
    {
        if (Selection.activeObject is TextAsset)
        {
            TextAsset textAsset = (TextAsset) Selection.activeObject;

            JsonArray jsonArray = SimpleJson.SimpleJson.DeserializeObject<JsonArray>(textAsset.text);


            _table = new TableClass();
            _tableSet = new TableSetClass();

            List<string> keyList = ((JsonObject) jsonArray[0]).Keys.ToList();
            _table.keyList[0] = keyList[0];
            for (int i = 1; i < keyList.Count; i++)
            {
                _table.keyList.Add(keyList[i]);
            }

            for (int i = 0; i < keyList.Count; i++)
            {
                if (i == 0)
                {
                    _table.typeList[0] = CheckType(jsonArray, i);
                }
                else
                {
                    _table.typeList.Add(CheckType(jsonArray, i));
                }
            }

            _tableSet.valueList.Clear();
            for (int i = 0; i < jsonArray.Count; i++)
            {
                _tableSet.valueList.Add(new TableDataClass(_table.typeList));
                JsonObject jsonObject = (JsonObject) jsonArray[i];
                for (int j = 0; j < _table.typeList.Count; j++)
                {
                    _tableSet.valueList[i].valueList[j] = jsonObject.Values.ToArray()[j].ToString();
                }
            }

            fpath = AssetDatabase.GUIDToAssetPath(Selection.assetGUIDs[0]);

            tips = "打开成功";
            tipsColor = Color.green;
        }
        else
        {
            tips = "打开失败，类型错误";
            tipsColor = Color.red;
        }
    }

    public TypeEnum CheckType(JsonArray jsonArray, int columIndex)
    {
        int num = 0;
        bool res = true;
        foreach (JsonObject jsonObject in jsonArray)
        {
            string vStr = jsonObject.Values.ToArray()[columIndex].ToString();
            res = int.TryParse(vStr, out num);
            if (!res)
            {
                break;
            }
        }

        if (res)
        {
            return TypeEnum.Int;
        }
        else
        {
            float num2 = 0;
            bool res2 = true;
            foreach (JsonObject jsonObject in jsonArray)
            {
                string vStr = jsonObject.Values.ToArray()[columIndex].ToString();
                res2 = float.TryParse(vStr, out num2);
                if (!res2)
                {
                    break;
                }
            }

            if (res2)
            {
                return TypeEnum.Float;
            }
            else
            {
                return TypeEnum.String;
            }
        }
    }

    private int CheckContent(int lineIndex)
    {
        int resIndex = -1;
        for (int i = 0; i < _table.typeList.Count; i++)
        {
            if (_table.typeList[i] == TypeEnum.Int)
            {
                int v;
                bool res = int.TryParse(_tableSet.valueList[lineIndex].valueList[i].ToString(), out v);
                if (!res)
                {
                    resIndex = i;
                }
            }
            else if (_table.typeList[i] == TypeEnum.Float)
            {
                float v;
                bool res = float.TryParse(_tableSet.valueList[lineIndex].valueList[i].ToString(), out v);
                if (!res)
                {
                    resIndex = i;
                }
            }
        }

        return resIndex;
    }

    private int[] CheckTag()
    {
        int[] res = new int[2];
        for (int i = 0; i < _table.keyList.Count - 1; i++)
        {
            for (int j = i + 1; j < _table.keyList.Count; j++)
            {
                if (_table.keyList[i] == _table.keyList[j])
                {
                    res[0] = i;
                    res[1] = j;
                    return res;
                }
            }
        }

        return res;
    }


    private int[] CheckIdRepeat()
    {
        int[] res = new int[3];
        for (int i = 0; i < _table.keyList.Count; i++)
        {
            if (_table.keyList[i].ToLower().Contains("id") && _table.typeList[i] == TypeEnum.Int)
            {
                for (int j = 0; j < _tableSet.valueList.Count; j++)
                {
                    for (int k = j + 1; k < _tableSet.valueList.Count - 1; k++)
                    {
                        if (int.Parse(_tableSet.valueList[j].valueList[i].ToString()) ==
                            int.Parse(_tableSet.valueList[k].valueList[i].ToString()))
                        {
                            res[0] = i;
                            res[1] = j;
                            res[2] = k;
                            return res;
                        }
                    }
                }
            }
        }

        return res;
    }

    public void SaveJson()
    {
        tips = "";
        int[] resArr = CheckTag();
        if (resArr[1] != 0)
        {
            tips = "保存失败，第" + (resArr[0] + 1) + "列与第" + (resArr[1] + 1) + "列列名重复！";
            tipsColor = Color.red;
            return;
        }


        for (int i = 0; i < _tableSet.valueList.Count; i++)
        {
            int res = CheckContent(i);
            if (res != -1)
            {
                tips = "保存失败，请检查第" + (i + 1) + "行，第" + (res + 1) + "列，类型错误！";
                tipsColor = Color.red;
                return;
            }
        }

        int[] resArr2 = CheckIdRepeat();
        if (resArr2[2] != 0)
        {
            tips = "检测到第" + (resArr2[0] + 1) + "列包含字符\"id\"且类型为Int，但第" + (resArr2[1] + 1) + "行与第" + (resArr2[2] + 1) +
                   "行数值重复，已保存成功！";
            tipsColor = Color.yellow;
        }


        string json = "[\n";
        for (int i = 0; i < _tableSet.valueList.Count; i++)
        {
            json += "    {\n";
            for (int j = 0; j < _table.keyList.Count; j++)
            {
                if (_table.typeList[j] == TypeEnum.String)
                {
                    if (j == _table.keyList.Count - 1)
                    {
                        json += "        \"" + _table.keyList[j] + "\" : \"" + _tableSet.valueList[i].valueList[j] +
                                "\"\n";
                    }
                    else
                    {
                        json += "        \"" + _table.keyList[j] + "\" : \"" + _tableSet.valueList[i].valueList[j] +
                                "\",\n";
                    }
                }
                else
                {
                    if (j == _table.keyList.Count - 1)
                    {
                        json += "        \"" + _table.keyList[j] + "\" : " + _tableSet.valueList[i].valueList[j] + "\n";
                    }
                    else
                    {
                        json += "        \"" + _table.keyList[j] + "\" : " + _tableSet.valueList[i].valueList[j] +
                                ",\n";
                    }
                }
            }

            if (i == _tableSet.valueList.Count - 1)
            {
                json += "    }\n";
            }
            else
            {
                json += "    },\n";
            }
        }

        json += "]";

        string dir = Path.GetDirectoryName(fpath);
        if (!Directory.Exists(fpath))
        {
            Directory.CreateDirectory(dir);
            AssetDatabase.Refresh();
        }

        FileInfo fileInfo = new FileInfo(fpath);
        StreamWriter streamWriter = fileInfo.CreateText();
        streamWriter.WriteLine(json);
        streamWriter.Close();
        AssetDatabase.Refresh();

        if (tips == "")
        {
            tips = "保存成功";
            tipsColor = Color.green;
        }
    }
}

public enum TypeEnum
{
    Int,
    Float,
    String,
//    List
}

public class TableClass
{
    public List<string> keyList;

    public List<TypeEnum> typeList;
//    public int kIndex;


    public TableClass()
    {
        keyList = new List<string>() {"new tag"};
        typeList = new List<TypeEnum>() {TypeEnum.Int};
    }
}

public class TableSetClass
{
    public List<TableDataClass> valueList;

    public TableSetClass()
    {
        valueList = new List<TableDataClass>();
        valueList.Add(new TableDataClass(new List<TypeEnum>() {TypeEnum.Int}));
    }
}

public class TableDataClass
{
    public List<object> valueList;
    public bool isEdit;

    public TableDataClass(List<TypeEnum> typeList)
    {
        valueList = new List<object>() { };
        isEdit = true;
        for (int i = 0; i < typeList.Count; i++)
        {
//            if (typeList[i] == TypeEnum.List)
//            {
//                valueList.Add(new Table());
//            }
//            else
            {
                valueList.Add("value" + i);
            }
        }
    }
}

public class Table
{
    public TableClass talbe;
    public TableSetClass tableSet;

    public Table()
    {
        talbe = new TableClass();
        tableSet = new TableSetClass();
    }
}